import darkdetect
from PySide6.QtCore import QObject, Signal, QProcess, Qt, QTimer
from PySide6.QtWidgets import QApplication
from utils.path_processor import resource_path
from models.manager.yunzai_manager import YunzaiManager
from models.manager.plugin_manager import PluginManager
from utils.decorators.decorators import yunzai_installer
import os
import json
import stat
import shutil


class MainViewModel(QObject):
    log_updated = Signal(str)
    instances_updated = Signal(list)
    terminal_created = Signal(str, object)

    def __init__(self):
        """初始化视图模型及其依赖管理器"""
        super().__init__()
        self.yunzai_mgr = YunzaiManager()  # Yunzai 实例管理器
        self.plugin_mgr = PluginManager()  # 插件管理器
        self._processes = {}  # 存储正在运行的进程
        self._init_theme_timer()

    def _init_theme_timer(self):
        self.theme_timer = QTimer()
        self.theme_timer.timeout.connect(self._check_theme_change)
        self.theme_timer.start(1000)  # 每秒检查一次
        self.last_dark_state = darkdetect.isDark()

    def _check_theme_change(self):
        try:
            with open(resource_path("config/config.json"), "r") as f:
                theme_setting = json.load(f).get("theme", "system")
        except FileNotFoundError:
            theme_setting = "system"

        if theme_setting != "system":
            return

        current_dark = darkdetect.isDark()
        if current_dark != self.last_dark_state:
            self.last_dark_state = current_dark
            app = QApplication.instance()
            theme = "dark" if current_dark else "light"
            try:
                with open(resource_path(f"resources/styles/{theme}.qss"), "r") as f:
                    app.setStyleSheet(f.read())
            except FileNotFoundError:
                pass

    def refresh_instances(self):
        """刷新并更新当前 Yunzai 实例列表"""
        self.instances_updated.emit(self.yunzai_mgr.instances)

    @yunzai_installer
    def install_yunzai(self, window, version, path, name):
        """
        安装 Yunzai 实例

        Args:
            version (str): Yunzai 版本号
            path (str): 安装路径
            name (str): 实例名称

        Returns:
            tuple: 包含进程对象、目标目录、版本和名称的元组
        """
        target_dir = os.path.join(path, name)
        if os.path.exists(target_dir):
            self.log_updated.emit(f"错误：目录已存在 {target_dir}")
            return None

        self.log_updated.emit(f"开始安装 {version} 到 {target_dir},实例名称为 {name}")
        process = QProcess()
        process.setWorkingDirectory(path)
        process.start("git", ["clone", "--progress", YunzaiManager.VERSIONS[version], name])
        return window, process, target_dir, version, name

    def start_yunzai(self, instances):
        current_item = instances.currentItem()
        if not current_item:
            return
        instance = json.loads(current_item.data(Qt.ItemDataRole.UserRole))
        process = QProcess(self)
        process.setWorkingDirectory(instance["path"])
        process.start("node", ["app.js"])

        process.readyReadStandardOutput.connect(
            lambda: self._handle_process_output(process, instance["name"], "stdout")
        )
        process.readyReadStandardError.connect(
            lambda: self._handle_process_output(process, instance["name"], "stderr")
        )

        self._processes[instance["name"]] = process
        self.terminal_created.emit(instance["name"], process)

    def _handle_process_output(self, process, name, output_type):
        if output_type == "stdout":
            text = process.readAllStandardOutput().data().decode('utf-8', 'ignore')
        else:
            text = process.readAllStandardError().data().decode('utf-8', 'ignore')

        if hasattr(self, "_terminals") and name in self._terminals:
            self._terminals[name].append(text)
        self.log_updated.emit(f"[{name}] {text.strip()}")

    def _post_install(self, window, process, target_dir, version, name):
        """
        安装后处理操作

        Args:
            process (QProcess): 安装进程对象
            target_dir (str): 目标安装目录
            version (str): Yunzai 版本号
            name (str): 实例名称
        """
        if process.exitCode() != 0:
            self.log_updated.emit(f"[ERROR] 克隆失败，退出码: {process.exitCode()}")
            return

        self.log_updated.emit("\n[INFO] 仓库克隆成功，开始安装流程...")
        self._install_global_pnpm(window, target_dir, version, name)

    def _install_global_pnpm(self, window, target_dir, version, name):
        """
        强制在目标目录执行全局 pnpm 安装

        Args:
            instance: Yunzai 实例对象
            target_dir (str): 目标安装目录
            version (str): Yunzai 版本号
            name (str): 实例名称
        """
        self.log_updated.emit("[INFO] pnpm安装中...")

        process = QProcess(window)
        process.setWorkingDirectory(target_dir)
        npm_cmd = "npm.cmd" if os.name == 'nt' else "npm"
        process.start(npm_cmd, ["install", "-g", "pnpm", "--registry=https://registry.npmmirror.com"])

        def on_installed():
            """pnpm 安装完成回调"""
            if process.exitCode() == 0:
                self.log_updated.emit("[INFO] pnpm安装成功")
                self._run_pnpm_install(window, target_dir, version, name)
            else:
                self.log_updated.emit("[ERROR] PNPM安装失败，请手动执行：npm install -g pnpm")
        process.finished.connect(on_installed)

    def _run_pnpm_install(self, window, target_dir, version, name):
        """
        执行pnpm依赖安装

        Args:
            instance: Yunzai实例对象
            target_dir (str): 目标安装目录
            version (str): Yunzai版本号
            name (str): 实例名称
        """
        self.log_updated.emit("[INFO] 依赖安装中")
        process = QProcess(window)
        process.setWorkingDirectory(target_dir)
        pnpm_cmd = "pnpm.cmd" if os.name == 'nt' else "pnpm"
        process.start(pnpm_cmd, ["install", "--registry=https://registry.npmmirror.com"])

        def on_finished():
            """pnpm 安装完成回调"""
            if process.exitCode() == 0:
                self._finalize_installation(window, target_dir, version, name)
            else:
                self.log_updated.emit(f"[ERROR] 依赖安装失败，退出码: {process.exitCode()}")
        process.finished.connect(on_finished)

    def _finalize_installation(self, window, target_dir, version, name):
        """
        完成安装流程并保存实例信息

        Args:
            instance: Yunzai实例对象
            target_dir (str): 目标安装目录
            version (str): Yunzai版本号
            name (str): 实例名称
        """
        self.log_updated.emit("[INFO] 依赖安装完成！")
        # 保存实例记录
        self.yunzai_mgr.add_instance({
            "name": name,
            "path": target_dir,
            "version": str(version)
        })
        self.yunzai_mgr.save_instances()
        self.refresh_instances()

    def uninstall_yunzai(self, name, path):
        """
        完全卸载 Yunzai 实例（增强版）

        Args:
            name (str): 实例名称
            path (str): 实例安装路径
        """
        abs_path = os.path.abspath(os.path.expanduser(path))

        # 停止进程（增加超时机制）
        if name in self._processes:
            process = self._processes.pop(name)
            process.terminate()
            if not process.waitForFinished(5000):  # 5秒超时
                self.log_updated.emit(f"[WARN] 实例 {name} 进程未正常退出")

        # 删除实例记录
        self.yunzai_mgr.remove_instance(name)

        # 删除逻辑
        def _on_rm_error(func, path, exc_info):
            """处理文件占用/权限问题"""
            os.chmod(path, stat.S_IWUSR | stat.S_IREAD)  # 跨平台权限修正
            func(path)  # 重试

        try:
            if os.path.exists(abs_path):
                shutil.rmtree(abs_path, onerror=_on_rm_error)
                self.log_updated.emit(f"[INFO] 实例 {name} 目录已删除: {abs_path}")
            else:
                self.log_updated.emit(f"[WARN] 目录不存在: {abs_path}")
        except Exception as e:
            self.log_updated.emit(f"[ERROR] 删除失败: {str(e)}")
        finally:
            self.refresh_instances()